
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;

namespace SmartPlant.WinCore;

/// <summary>
/// 内部反射静态类
/// </summary>
public static class Reflect
{
    /// <summary>
    /// 获取入口程序集
    /// </summary>
    /// <returns></returns>
    public static Assembly GetEntryAssembly()
    {
        return Assembly.GetEntryAssembly();
    }

    /// <summary>
    /// 根据程序集名称获取运行时程序集
    /// </summary>
    /// <param name="assemblyName"></param>
    /// <returns></returns>
    public static Assembly GetAssembly(string assemblyName)
    {
        // 加载程序集
        return AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyName));
    }

    /// <summary>
    /// 根据路径加载程序集
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    public static Assembly? LoadAssembly(string path)
    {
        if (!File.Exists(path)) return default;
        return Assembly.LoadFrom(path);
    }

    /// <summary>
    /// 通过流加载程序集
    /// </summary>
    /// <param name="assembly"></param>
    /// <returns></returns>
    public static Assembly LoadAssembly(MemoryStream assembly)
    {
        return Assembly.Load(assembly.ToArray());
    }

    /// <summary>
    /// 根据程序集名称、类型完整限定名获取运行时类型
    /// </summary>
    /// <param name="assemblyName"></param>
    /// <param name="typeFullName"></param>
    /// <returns></returns>
    public static Type GetType(string assemblyName, string typeFullName)
    {
        return GetAssembly(assemblyName).GetType(typeFullName);
    }

    /// <summary>
    /// 根据程序集和类型完全限定名获取运行时类型
    /// </summary>
    /// <param name="assembly"></param>
    /// <param name="typeFullName"></param>
    /// <returns></returns>
    public static Type GetType(Assembly assembly, string typeFullName)
    {
        return assembly.GetType(typeFullName);
    }

    /// <summary>
    /// 根据程序集和类型完全限定名获取运行时类型
    /// </summary>
    /// <param name="assembly"></param>
    /// <param name="typeFullName"></param>
    /// <returns></returns>
    public static Type GetType(MemoryStream assembly, string typeFullName)
    {
        return LoadAssembly(assembly).GetType(typeFullName);
    }

    /// <summary>
    /// 获取程序集名称
    /// </summary>
    /// <param name="assembly"></param>
    /// <returns></returns>
    public static string GetAssemblyName(Assembly assembly)
    {
        return assembly.GetName().Name;
    }

    /// <summary>
    /// 获取程序集名称
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static string GetAssemblyName(Type type)
    {
        return GetAssemblyName(type.GetTypeInfo());
    }

    /// <summary>
    /// 获取程序集名称
    /// </summary>
    /// <param name="typeInfo"></param>
    /// <returns></returns>
    public static string GetAssemblyName(TypeInfo typeInfo)
    {
        return GetAssemblyName(typeInfo.Assembly);
    }

    /// <summary>
    /// 加载程序集类型，支持格式：程序集;网站类型命名空间
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    public static Type GetStringType(string str)
    {
        var typeDefinitions = str.Split(";");
        return GetType(typeDefinitions[0], typeDefinitions[1]);
    }

    /// <summary>
    /// 获取属性值。
    /// </summary>
    /// <param name="instance"></param>
    /// <param name="propName"></param>
    /// <returns></returns>
    public static object? GetPropValue(object instance, string propName)
    {
        var prop = instance.GetType().GetProperty(propName);
        if (prop == null)
        {
            prop = Reflect.GetProperty(instance.GetType(), propName);
        }
        var value = prop?.GetValue(instance);
        return value;
    }
    /// <summary>
    /// 转换值。避免属性值和属性定义的类型不一样而报错
    /// </summary>
    /// <param name="attrDef"></param>
    /// <param name="originalValue"></param>
    /// <returns></returns>
    public static object convertValue(PropertyInfo attrDef, string originalValue)
    {
        var valueTypeDef = attrDef.PropertyType;
        object res = new object();
        if (decimal.TryParse(originalValue, out decimal value))
        {
            if (valueTypeDef == typeof(decimal))
            {
                res = value;
            }
            else if (valueTypeDef == typeof(decimal?))
            {
                res = (decimal?)value;
            }
        }
        else
        {
            if (valueTypeDef == typeof(decimal?))
            {
                res = null; // 如果转换失败且属性是可空的，则设置为null  
            }
            // 对于非可空decimal，如果转换失败，你可能需要决定如何处理这种情况（例如，抛出一个异常或设置一个默认值）  
        }



        //if (valueTypeDef.FullName.ToLower().Contains("nullable"))
        //{
        //    switch (valueTypeDef.GenericTypeArguments[0].Name)
        //    {
        //        case "Decimal":
        //            decimal? _item;
        //            decimal.TryParse(originalValue, out _item);

        //            if (_item == Math.Truncate(_item))
        //            {
        //                //比如15和15.0
        //                int.TryParse(originalValue, out int _item3);
        //                value = _item3;
        //            }
        //            else
        //            {
        //                value = _item;

        //            }
        //            break;
        //        case "Int32":
        //            int _item2;
        //            int.TryParse(originalValue, out _item2);
        //            value = _item2;
        //            break;
        //        default:
        //            break;
        //    }
        //}
        //else
        //{
        //    value = Convert.ChangeType(originalValue, valueTypeDef);
        //}
        return value;
    }

    public static object ConvertStringToPropertyType(PropertyInfo propDef, string stringValue)
    {
        var targetType = propDef.PropertyType;
        if (targetType == typeof(decimal))
        {
            if (decimal.TryParse(stringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out decimal decimalValue))
            {
                return decimalValue;
            }
        }
        else if (targetType == typeof(decimal?))
        {
            if (decimal.TryParse(stringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out decimal decimalValue))
            {
                return (decimal?)decimalValue;
            }
            return null; // 如果转换失败，对于可空类型返回null  
        }
        else if (targetType == typeof(string))
        {
            return stringValue; // 字符串类型直接返回原值  
        }
        else if (targetType == typeof(int))
        {
            if (int.TryParse(stringValue, out int intValue))
            {
                return intValue;
            }
        }
        else if (targetType == typeof(int?))
        {
            if (int.TryParse(stringValue, out int intValue))
            {
                return (int?)intValue;
            }
            return null; // 如果转换失败，对于可空类型返回null  
        }
        // 可以继续添加其他类型的转换逻辑  

        throw new ArgumentException($"Cannot convert string to type {targetType.Name}.");
    }

    /// <summary>
    /// 获取属性值。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="instance"></param>
    /// <param name="propName"></param>
    /// <returns></returns>
    public static T? GetPropValue<T>(object instance, string propName)
    {
        var prop = instance.GetType().GetProperty(propName);
        var value = (T)prop.GetValue(instance);
        return value;
    }


    /// <summary>
    /// 获取字段值。
    /// </summary>
    /// <param name="instance"></param>
    /// <param name="fieldName"></param>
    /// <returns></returns>
    public static object? GetFieldValue(object instance, string fieldName)
    {
        var prop = instance.GetType().GetField(fieldName);
        var value = prop.GetValue(instance);
        return value;
    }

    /// <summary>
    /// 获取字段值。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="instance"></param>
    /// <param name="fieldName"></param>
    /// <returns></returns>
    public static T? GetFieldValue<T>(object instance, string fieldName)
    {
        var prop = instance.GetType().GetField(fieldName);
        var value = (T)prop.GetValue(instance);
        return value;
    }

    /// <summary>
    /// 设置属性值。
    /// </summary>
    /// <param name="instance"></param>
    /// <param name="propName"></param>
    /// <param name="value"></param>
    public static void SetPropValue(object instance, string propName, object value)
    {
        var prop = instance.GetType().GetProperty(propName);
        prop.SetValue(instance, value);
    }

    #region GetAttribute
    /// <summary>
    /// 获取指定<see cref="PropertyInfo"/>对象的是否存在指定的自定义属性。
    /// </summary>
    /// <param name="property"></param>
    /// <param name="attributeType"></param>
    /// <returns></returns>
    public static bool HasAttributeOf(this PropertyInfo property, Type attributeType)
    {
        object[] attributes = property.GetCustomAttributes(attributeType, true);
        return attributes.Length > 0;
    }

    /// <summary>
    /// 获取指定<see cref="PropertyInfo"/>对象的是否存在指定的自定义属性。
    /// </summary>
    /// <typeparam name="TAttribute"></typeparam>
    /// <param name="propertyInfo"></param>
    /// <returns></returns>
    public static bool HasAttributeOf<TAttribute>(this PropertyInfo propertyInfo)
    {
        object[] attributes = propertyInfo.GetCustomAttributes(typeof(TAttribute), true);
        return attributes.Length > 0;
    }

    /// <summary>
    /// 获取指定<see cref="PropertyInfo"/>对象的中指定的自定义属性。
    /// </summary>
    /// <typeparam name="TAttribute"></typeparam>
    /// <param name="propertyInfo"></param>
    /// <returns></returns>
    public static TAttribute? GetAttributeOf<TAttribute>(this PropertyInfo propertyInfo)
    {
        object[] attributes = propertyInfo.GetCustomAttributes(typeof(TAttribute), true);
        if (attributes.Length == 0)
        {
            return default;
        }
        return (TAttribute)attributes[0];
    }
    #endregion

    #region FindAttribute
    /// <summary>
    /// 在指定的枚举实例中查找属性。
    /// </summary>
    /// <param name="instance">枚举项。</param>
    /// <param name="attributeType">查找你想要的属性.</param>
    /// <returns>返回属性值.</returns>
    public static Attribute? GetAttribute(Enum instance, Type attributeType)
    {
        Type type = instance.GetType();
        MemberInfo[] memberInfos = type.GetMember(instance.ToString());
        if (memberInfos != null && memberInfos.Length > 0)
        {
            MemberInfo memberInfo = memberInfos[0] as MemberInfo;
            IList attributes = GetAttributes(false, memberInfo, attributeType);
            if (attributes != null && attributes.Count > 0)
                return attributes[0] as Attribute;
        }
        return null;
    }
    #endregion

    #region FindAttributes
    /// <summary>
    /// Get enum item's attribute value in attribute list.
    /// </summary>
    /// <param name="allowDuplicates">Allow duplicates.</param>
    /// <param name="memberInfo">MemberInfo</param>
    /// <param name="attributeTypes">Attribute list</param>
    /// <returns>Attribute value list</returns>
    public static IList GetAttributes(bool allowDuplicates, MemberInfo memberInfo, params Type[] attributeTypes)
    {
        IList result = new ArrayList();
        foreach (Type attributeType in attributeTypes)
        {
            object[] attributes = memberInfo.GetCustomAttributes(attributeType, true);
            int max = allowDuplicates ? attributes.Length : 1;
            if (attributes != null && attributes.Length > 0)
            {
                for (int i = 0; i < max; i++)
                {
                    result.Add(attributes[i]);
                }
            }
        }
        return result;
    }
    #endregion

    #region FindPropertys
    /// <summary>
    /// 在指定的类型中查找属性。
    /// </summary>
    /// <param name="type">指定的类型</param>
    /// <returns>返回属性数据。</returns>
    public static PropertyInfo[] GetPropertys<T>()
    {
        return GetPropertys(typeof(T));
    }

    /// <summary>
    /// 在指定的类型中查找属性。
    /// </summary>
    /// <param name="type">指定的类型</param>
    /// <param name="bindingAttr"></param>
    /// <returns>返回属性数据。</returns>
    public static PropertyInfo[] GetPropertys<T>(BindingFlags bindingAttr)
    {
        return GetPropertys(typeof(T), bindingAttr);
    }

    /// <summary>
    /// 在指定的类型中查找属性。
    /// </summary>
    /// <param name="type">指定的类型</param>
    /// <returns>返回属性数据。</returns>
    public static PropertyInfo[] GetPropertys(this Type type)
    {
        return type.GetProperties();
    }

    /// <summary>
    /// 在指定的类型中查找属性。
    /// </summary>
    /// <param name="type">指定的类型</param>
    /// <param name="bindingAttr"></param>
    /// <returns>返回属性数据。</returns>
    public static PropertyInfo[] GetPropertys(this Type type, BindingFlags bindingAttr)
    {
        return type.GetProperties(bindingAttr);
    }

    /// <summary>
    /// 获取指定类型中的属性信息。
    /// </summary>
    /// <param name="type"></param>
    /// <param name="propertyName"></param>
    /// <returns></returns>
    public static PropertyInfo GetProperty(this Type type, string propertyName)
    {
        var res = type.GetProperty(propertyName);
        if (res == null)
        {
            foreach (var y in type.GetProperties())
            {
                CustomAttributeData cusAttrs = y.CustomAttributes.FirstOrDefault((CustomAttributeData X) => X.AttributeType.Name == "SugarColumn");
                if (cusAttrs != null)
                {
                    var spiCol = cusAttrs.NamedArguments.FirstOrDefault((CustomAttributeNamedArgument x) => x.MemberName == "ColumnName").TypedValue.Value.ToString();
                    if (spiCol.ToUpper() == propertyName.ToUpper())
                    {
                        return y;
                    }
                }
            }
            return res;
        }
        else
        {
            return res;
        }
    }

    /// <summary>
    /// 获取字段特性
    /// </summary>
    /// <param name="field"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static T? GetDescriptionValue<T>(this FieldInfo field) where T : Attribute
    {
        // 获取字段的指定特性，不包含继承中的特性
        object[] customAttributes = field.GetCustomAttributes(typeof(T), false);

        // 如果没有数据返回null
        return customAttributes.Length > 0 ? (T)customAttributes[0] : null;
    }
    #endregion
}